package com.ljd.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ljd.common.to.SkuHasStockVo;
import com.ljd.common.to.SkuReductionTo;
import com.ljd.common.to.SpuBoundTo;
import com.ljd.common.to.es.SkuEsModel;
import com.ljd.common.utils.R;
import com.ljd.gulimall.product.entity.*;
import com.ljd.gulimall.product.feign.CouponFeign;
import com.ljd.gulimall.product.feign.SearchFeign;
import com.ljd.gulimall.product.feign.WareFeign;
import com.ljd.gulimall.product.service.*;
import com.ljd.gulimall.product.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljd.common.utils.PageUtils;
import com.ljd.common.utils.Query;

import com.ljd.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;
    @Autowired
    SpuImagesService spuImagesService;
    @Autowired
    CouponFeign couponFeign;
    @Autowired
    AttrService attrService;
    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    SkuInfoService skuInfoService;
    @Autowired
    SkuImagesService skuImagesService;
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    BrandService brandService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    WareFeign wareFeign;
    @Autowired
    SearchFeign searchFeign;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo spuInfo) {

        // 保存spu基本信息
        SpuInfoEntity infoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuInfo, infoEntity);
        infoEntity.setCreateTime(new Date());
        infoEntity.setUpdateTime(new Date());
        this.save(infoEntity);
        // 保存spu描述信息
        SpuInfoDescEntity infoDesc = new SpuInfoDescEntity();
        infoDesc.setSpuId(infoEntity.getId());
        String s = String.join(",", spuInfo.getDecript());
        infoDesc.setDecript(s);
        spuInfoDescService.save(infoDesc);
        // 保存spu图片信息
        List<SpuImagesEntity> spuImagesEntities = spuInfo.getImages().stream().map(img -> {
            SpuImagesEntity spuImages = new SpuImagesEntity();
            spuImages.setSpuId(infoEntity.getId());
            spuImages.setImgUrl(img);
            return spuImages;
        }).collect(Collectors.toList());
        spuImagesService.saveBatch(spuImagesEntities);
        // 保存spu积分信息
        Bounds bounds = spuInfo.getBounds();
        SpuBoundTo to = new SpuBoundTo();
        to.setSpuId(infoEntity.getId());
        to.setGrowBounds(bounds.getGrowBounds());
        to.setBuyBounds(bounds.getGrowBounds());
        R r = couponFeign.saveSpuBounds(to);
        if(r.getCode() != 0) {
            log.error("远程保存spu积分信息失败");
        }
        // 保存spu规格参数
        List<BaseAttrs> baseAttrs = spuInfo.getBaseAttrs();
        if(baseAttrs != null && baseAttrs.size() > 0) {
            List<Long> attrIds = baseAttrs.stream().map(BaseAttrs::getAttrId).collect(Collectors.toList());
            List<AttrEntity> attrEntities = (List<AttrEntity>) attrService.listByIds(attrIds);;
            List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(attr -> {
                ProductAttrValueEntity entity = new ProductAttrValueEntity();
                entity.setSpuId(infoEntity.getId());
                entity.setAttrId(attr.getAttrId());
                entity.setAttrValue(attr.getAttrValues());
                entity.setQuickShow(attr.getShowDesc());
                String s1 = attrEntities.stream().filter(attrEntity -> Objects.equals(attrEntity.getAttrId(), attr.getAttrId())).map(AttrEntity::getAttrName)
                        .findFirst().orElse(null);
                entity.setAttrName(s1);
                return entity;
            }).collect(Collectors.toList());
            productAttrValueService.saveBatch(productAttrValueEntities);
        }

        List<Skus> skus = spuInfo.getSkus();
        for (Skus sku : skus) {
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            skuInfoEntity.setBrandId(spuInfo.getBrandId());
            skuInfoEntity.setSpuId(infoEntity.getId());
            skuInfoEntity.setCatalogId(spuInfo.getCatalogId());
            skuInfoEntity.setPrice(sku.getPrice());
            skuInfoEntity.setSkuName(sku.getSkuName());
            skuInfoEntity.setSkuTitle(sku.getSkuTitle());
            skuInfoEntity.setSaleCount(0L);
            skuInfoEntity.setSkuSubtitle(sku.getSkuSubtitle());
            List<Images> images = sku.getImages();
            String imgUrl = images.stream().filter(img -> Objects.equals(img.getDefaultImg(), 1)).map(Images::getImgUrl)
                    .findFirst().orElse(null);
            skuInfoEntity.setSkuDefaultImg(imgUrl);
            // 保存sku基本信息
            skuInfoService.save(skuInfoEntity);
            // 保存sku图片信息
            List<Images> imgs = images.stream().filter(img -> !Objects.equals(img.getImgUrl(), "") && !Objects.equals(img.getImgUrl(), null)).collect(Collectors.toList());
            if(imgs.size() > 0) {
                List<SkuImagesEntity> skuImagesEntities = imgs.stream().map(img -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                    skuImagesEntity.setImgUrl(img.getImgUrl());
                    skuImagesEntity.setDefaultImg(img.getDefaultImg());
                    return skuImagesEntity;
                }).collect(Collectors.toList());
                skuImagesService.saveBatch(skuImagesEntities);
            }
            // 保存sku销售属性信息
            List<Attr> attrs = sku.getAttr();
            if(attrs != null && attrs.size() > 0) {
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream().map(attr -> {
                    SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                    skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                    skuSaleAttrValueEntity.setAttrId(attr.getAttrId());
                    skuSaleAttrValueEntity.setAttrName(attr.getAttrName());
                    skuSaleAttrValueEntity.setAttrValue(attr.getAttrValue());
                    return skuSaleAttrValueEntity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
            }
            // 保存spu会员价格、满减、打折信息
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            BeanUtils.copyProperties(sku, skuReductionTo);
            R r1 = couponFeign.saveReduction(skuReductionTo);
            if(r1.getCode() != 0) {
                log.error("远程保存spu积分信息失败");
            }
        }

    }

    @Override
    public PageUtils queryPageByCondtion(Map<String, Object> params) {

        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        String catelogId = (String) params.get("catelogId");
        String brandId = (String) params.get("brandId");
        String status = (String) params.get("status");

        if(StringUtils.isNotBlank(key)) {
            wrapper.and(w -> {
                w.eq("id", key).or().like("spu_name",key);
            });
        }
        if(StringUtils.isNotBlank(catelogId)) {
            wrapper.eq("catalog_id",catelogId);
        }
        if(StringUtils.isNotBlank(brandId) && !Objects.equals(brandId, "0")) {
            wrapper.eq("brand_id", brandId);
        }
        if(StringUtils.isNotBlank(status)) {
            wrapper.eq("publish_status", status);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );
        PageUtils pageUtils = new PageUtils(page);
        List<SpuInfoEntity> records = page.getRecords();
        List<Long> brandIds = records.stream().map(SpuInfoEntity::getBrandId).collect(Collectors.toList());
        List<Long> catIds = records.stream().map(SpuInfoEntity::getCatalogId).collect(Collectors.toList());
        List<BrandEntity> brandEntities = (List<BrandEntity>) brandService.listByIds(brandIds);
        List<CategoryEntity> categoryEntities = (List<CategoryEntity>) categoryService.listByIds(catIds);
        List<SpuInfoEntity> spuInfoEntities = records.stream().peek(spuInfoEntity -> {
            BrandEntity brand = brandEntities.stream().filter(brandEntity -> Objects.equals(brandEntity.getBrandId(), spuInfoEntity.getBrandId()))
                    .findFirst().orElse(new BrandEntity());
            spuInfoEntity.setBrandName(brand.getName());
            CategoryEntity category = categoryEntities.stream().filter(categoryEntity -> Objects.equals(categoryEntity.getCatId(), spuInfoEntity.getCatalogId()))
                    .findFirst().orElse(new CategoryEntity());
            spuInfoEntity.setCatalogName(category.getName());
        }).collect(Collectors.toList());
        pageUtils.setList(spuInfoEntities);

        return pageUtils;
    }

    @Transactional
    @Override
    public void up(Long spuId) {
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.list(new LambdaQueryWrapper<SkuInfoEntity>().eq(SkuInfoEntity::getSpuId, spuId));
        SpuInfoEntity spuInfoEntity = this.getById(spuId);

        BrandEntity brandEntity = brandService.getById(spuInfoEntity.getBrandId());
        CategoryEntity categoryEntity = categoryService.getById(spuInfoEntity.getCatalogId());

        List<Long> skuInfoIds = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        R stock = wareFeign.getSkuHasStock(skuInfoIds);
        List<SkuHasStockVo> skuHasStockVos = stock.getData(new TypeReference<List<SkuHasStockVo>>() {
        });
        Map<Long, Boolean> map = skuHasStockVos.stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, SkuHasStockVo::getHasStock));

        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
        List<Long> attrIds = productAttrValueEntities.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
        List<Attr> attrs = attrService.getSearchTypeAttr(attrIds);
        List<SkuEsModel.Attr> attrList = attrs.stream().map(attr -> {
            SkuEsModel.Attr attr1 = new SkuEsModel.Attr();
            attr1.setAttrId(attr.getAttrId());
            attr1.setAttrName(attr.getAttrName());
            attr1.setAttrValue(attr.getAttrValue());
            return attr1;
        }).collect(Collectors.toList());
        List<SkuEsModel> skuEsModels = skuInfoEntities.stream().map(skuInfoEntity -> {
            SkuEsModel model = new SkuEsModel();
            BeanUtils.copyProperties(skuInfoEntity, model);
            model.setSkuPrice(skuInfoEntity.getPrice());
            model.setSkuImg(skuInfoEntity.getSkuDefaultImg());
            model.setHotScore(0L);
            //  private Boolean hasStock;
            Boolean aBoolean = map.get(skuInfoEntity.getSkuId());
            model.setHasStock(aBoolean != null && aBoolean);
            model.setBrandName(brandEntity.getName());
            model.setBrandImg(brandEntity.getLogo());
            model.setCatalogName(categoryEntity.getName());

            //  private Long attrId;
            //        private String attrName;
            //        private String attrValue;
            model.setAttrs(attrList);
            return model;
        }).collect(Collectors.toList());

        // 保存到es
        R r = searchFeign.productStatusUp(skuEsModels);
        if(r.getCode() == 0) {
            // 索引数据保存es成功，修改spu状态
            SpuInfoEntity entity = new SpuInfoEntity();
            entity.setId(spuId);
            entity.setPublishStatus(1);
            entity.setUpdateTime(new Date());
            this.updateById(entity);
        } else {
            //TODO 重复调用？接口幂等性:重试机制 (尝试保存索引数据到es)
        }
    }

}